#include "stdafx.h"
#include "wf_drawlineangle.h"
#include "pf_snapper.h"



WF_DrawLineAngle::WF_DrawLineAngle(PF_Container& container,
        PF_GraphicView& graphicView,
        double angle,
        bool fixedAngle)
        :PF_PreviewActionInterface("Draw lines with given angle",
                           container, graphicView) {

    this->angle = angle;
    length = 1.0;
    snpPoint = 0;
    this->fixedAngle = fixedAngle;
    pos = PF_Vector(false);
    reset();
}



WF_DrawLineAngle::~WF_DrawLineAngle() {}


QAction* WF_DrawLineAngle::createGUIAction(LX_Define::ActionType type, QObject* /*parent*/) {
    QAction* action=NULL;
	
	if (type==LX_Define::ActionDrawLineAngle) {
		// tr("&Angle"),
		// "Line: Angle"
		action = new QAction(tr("&Angle"),  NULL);
		action->setIcon(QIcon(":/extui/linesangle.png"));
	    //action->zetStatusTip(tr("Draw lines with a given angle"));
	}
	else if (type==LX_Define::ActionDrawLineHorizontal) {
                    //  tr("Line: Horizontal"),
            action = new QAction(tr("&Horizontal"),  NULL);
                    action->setIcon(QIcon(":/extui/lineshor.png"));
            //action->zetStatusTip(tr("Draw horizontal lines"));
	}
	else if (type==LX_Define::ActionDrawLineVertical) {
                    // tr("H&orizontal / Vertical"),
            action = new QAction(tr("Vertical"), NULL);
                    action->setIcon(QIcon(":/extui/linesver.png"));
            //action->zetStatusTip(tr("Draw vertical lines"));
	}
    return action;
}

void WF_DrawLineAngle::reset() {
    data = PF_LineAttribute(PF_Vector(false),
                       PF_Vector(false));
}



void WF_DrawLineAngle::init(int status) {
    PF_PreviewActionInterface::init(status);

    reset();
}



void WF_DrawLineAngle::trigger() {
    PF_PreviewActionInterface::trigger();

    preparePreview();
    PF_Line* line = new PF_Line(container,
                                data);
    line->setLayerToActive();
    line->setPenToActive();
    container->addEntity(line);

    // upd. undo list:
    if (document!=NULL) {
        document->startUndoCycle();
        document->addUndoable(line);
        document->endUndoCycle();
    }
	
    graphicView->moveRelativeZero(data.startpoint);
	graphicView->redraw(LX_Define::RedrawDrawing);
    PF_DEBUG->print("PF_ActionDrawLineAngle::trigger(): line added: %d",
                    line->getId());
}



void WF_DrawLineAngle::mouseMoveEvent(PF_MouseEvent* e) {
    PF_DEBUG->print("PF_ActionDrawLineAngle::mouseMoveEvent begin");

    if (getStatus()==SetPos) {
        pos = snapPoint(e);
        deletePreview();
        preparePreview();
        preview->addEntity(new PF_Line(preview,
                                       data));
        drawPreview();
    }

    PF_DEBUG->print("PF_ActionDrawLineAngle::mouseMoveEvent end");
}



void WF_DrawLineAngle::mouseReleaseEvent(PF_MouseEvent* e) {
    if (e->button()==Qt::LeftButton) {
        if (getStatus()==SetPos) {
            PF_CoordinateEvent ce(snapPoint(e));
            coordinateEvent(&ce);
        }
    } else if (e->button()==Qt::RightButton) {
        deletePreview();
        init(getStatus()-1);
    }
}


void WF_DrawLineAngle::preparePreview() {
    PF_Vector p1, p2;
    // End:
    if (snpPoint == 2) {
        p2.setPolar(length * -1, angle);
    } else {
        p2.setPolar(length, angle);
    }

    // Middle:
    if (snpPoint == 1) {
        p1 = pos - (p2 / 2);
    } else {
        p1 = pos;
    }

    p2 += p1;
    data = PF_LineAttribute(p1, p2);
}


void WF_DrawLineAngle::coordinateEvent(PF_CoordinateEvent* e) {
    if (e==NULL) {
        return;
    }

    switch (getStatus()) {
    case SetPos:
        pos = e->getCoordinate();
        trigger();
        break;

    default:
        break;
    }
}



void WF_DrawLineAngle::commandEvent(PF_CommandEvent* e) {
    PF_String c = e->getCommand().lower();

    if (checkCommand("help", c)) {
        PF_DIALOGFACTORY->commandMessage(msgAvailableCommands()
                                         + getAvailableCommands().join(", "));
        return;
    }

    switch (getStatus()) {
    case SetPos:
        if (!fixedAngle && checkCommand("angle", c)) {
            deletePreview();
            setStatus(SetAngle);
        } else if (checkCommand("length", c)) {
            deletePreview();
            setStatus(SetLength);
        }
        break;

    case SetAngle: {
            bool ok;
            double a = PF_Math::eval(c, &ok);
            if (ok==true) {
                angle = PF_Math::deg2rad(a);
            } else {
                PF_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
            }
            PF_DIALOGFACTORY->requestOptions(this, true, true);
            setStatus(SetPos);
        }
        break;

    case SetLength: {
            bool ok;
            double l = PF_Math::eval(c, &ok);
            if (ok==true) {
                length = l;
            } else {
                PF_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
            }
            PF_DIALOGFACTORY->requestOptions(this, true, true);
            setStatus(SetPos);
        }
        break;

    default:
        break;
    }
}



PF_StringList WF_DrawLineAngle::getAvailableCommands() {
    PF_StringList cmd;

    switch (getStatus()) {
    case SetPos:
        if (!fixedAngle) {
            cmd += command("angle");
        }
        cmd += command("length");
        break;
    default:
        break;
    }

    return cmd;
}


void WF_DrawLineAngle::updateMouseButtonHints() {
    switch (getStatus()) {
    case SetPos:
        PF_DIALOGFACTORY->updateMouseWidget(tr("Specify position"),
                                            tr("Cancel"));
        break;

    case SetAngle:
        PF_DIALOGFACTORY->updateMouseWidget(tr("Enter angle:"), tr("Back"));
        break;

    case SetLength:
        PF_DIALOGFACTORY->updateMouseWidget(tr("Enter length:"), tr("Back"));
        break;

    default:
        break;
    }
}



void WF_DrawLineAngle::showOptions() {
    PF_ActionInterface::showOptions();

    PF_DIALOGFACTORY->requestOptions(this, true);
}



void WF_DrawLineAngle::hideOptions() {
    PF_ActionInterface::hideOptions();

    PF_DIALOGFACTORY->requestOptions(this, false);
}



void WF_DrawLineAngle::updateMouseCursor() {
    graphicView->setMouseCursor(LX_Define::CadCursor);
}



void WF_DrawLineAngle::updateToolBar() {
    if (!isFinished()) {
        PF_DIALOGFACTORY->requestToolBar(LX_Define::ToolBarSnap);
    } else {
        PF_DIALOGFACTORY->requestToolBar(LX_Define::ToolBarLines);
    }
}

// EOF
